<?php
/**
 *  Created by Mient-jan Stelling [mient-jan@mediamonks.com].
 *  Copyright (c) 2008 MediaMonks. All rights reserved.
 */

/**
 * Spectus_Table_Hierarch_Row_Abstract
 *
 * @todo major recode of class 
 * @author Mient-jan Stelling
 **/
abstract class Spectus_Hierarch_Table_Abstract extends Spectus_Default_Table_Abstract 
{
	protected $_rowClass = 'Spectus_Hierarch_Table_Row';
	
	protected $_urlColumn;
	protected $_permaUrlColumn;
	
	/**
	 * Enter description here...
	 *
	 */
	function __construct()
	{
		if( empty( $this->_urlColumn ))
		{
			throw new Exception(' _urlColumn is not set is needed for Spectus_Hierarch_Table_Abstract. is used for making url\'s');
		}
		
		if( empty( $this->_permaUrlColumn ))
		{
			throw new Exception(' _permaUrlColumn is not set is needed for Spectus_Hierarch_Table_Abstract. is used for making url\'s');
		}
		
		parent::__construct();
	}

	/**
	 * Enter description here...
	 *
	 * @param $argStr
	 * @return string
	 */
	public function info( $argStr = NULL )
	{
		switch( $argStr )
		{
			case 'permaUrlColumn':
			{
				return $this->_permaUrlColumn;
				break;
			}
			
			case 'urlColumn':
			{
				return $this->_urlColumn;
				break;
			}
		}
		
		return parent::info( $argStr );
	}
	
	public function findFirstRow()
	{
		$objSelect = $this->select()
			->order('lft')
			->limit(1);
			
		return parent::fetchAll( $objSelect )->current();
	}
	
	public function fetchChildren()
	{
		
	}
	
	public function fetchParents()
	{
		
	}
	
	/**
	 * Enter description here...
	 *
	 * @param Spectus_Default_Table_Row_Abstract $argMix.
	 */
	public function fetchSiblings( Spectus_Hierarch_Table_Row_Abstract $argObjRow )
	{
		$intPrimary = current( (array) $this->_primary );
		
		$objSelect = $this->select()
			->setIntegrityCheck(false)
			->from(
				array('node'=> $this->_name), 
				array(
					'*',
					'active' => new Zend_Db_Expr('IF( LOCATE(node.' . $this->_permaUrlColumn . ',"' . $argStrUrl . '") > 0 ,1,0)')
				)
			)
			->from(
				array('parent'=>$this->_name),
				array(
					'depth' => new Zend_Db_Expr('COUNT(parent.id) - (sub_tree.depth + 1)'),
					'url' => new Zend_Db_Expr('GROUP_CONCAT(parent.' . $this->_permaUrlColumn . ' SEPARATOR "/")')
					
				)
			)
			->from(array('sub_parent'=>$this->_name),array())
			->from(array(
				'sub_tree'=> $this->select()
					->setIntegrityCheck(false)
					->from(
						array(
							'node'=>$this->_name
						),
						array('id')
					)
					->from(
						array('parent'=>$this->_name), 
						array('depth' => new Zend_Db_Expr('COUNT(parent.' . $intPrimary . ') - 1'))
					)
					->where('node.lft BETWEEN parent.lft AND parent.rgt')
					->where('node.id = ?', $argObjRow->id )
					->group('node.id')
					->order('node.lft')
			),array())
			->where('node.lft BETWEEN parent.lft AND parent.rgt')
			->where('node.lft BETWEEN sub_parent.lft AND sub_parent.rgt')
			->where('sub_parent.id = sub_tree.id')
			->group('node.id')
			
			->order('node.lft')
			->having('depth = ?', 1);
			
		return parent::fetchAll( $objSelect );		
	}
		
	public function findByUrl( $argStrUrl = false )
	{
		$intPrimary = current( (array) $this->_primary );
		
		$objSelect = $this->select()
			->setIntegrityCheck(false)
			->from(array('node'=>$this->_name))
			->from(array(
				'sub_tree'=> $this->select()
					->setIntegrityCheck(false)
					->from(
						array('node'=>$this->_name),
						array(
							'depth' => new Zend_Db_Expr('COUNT(parent.' . $intPrimary . ') - 1'),
							'id'
						)
					)
					->from(
						array(
							'parent'=>$this->_name
						), 
						array(
							'url' => new Zend_Db_Expr('GROUP_CONCAT(parent.' . $this->_permaUrlColumn . ' ORDER BY parent.lft SEPARATOR "/")')
						)
					)
					->where('node.lft BETWEEN parent.lft AND parent.rgt')
					->group('node.id')
					->order('node.lft')
			))
			->where('node.' . $intPrimary . ' = sub_tree.' . $intPrimary );
		
		if( $argStrUrl )
		{
			$objSelect->where('sub_tree.url = ?', $argStrUrl );
		}
			
		$objSelect->order('node.lft');
		
		return parent::fetchAll( $objSelect );
		
	}

	public function fetchAll( $objSelect = NULL )
	{
		if( is_null($objSelect) )
		{
			$intPrimary = current( (array) $this->_primary );
	
			$objSelect = $this->select()
				->setIntegrityCheck(false)
				->from(array('node'=> $this->_name ),array('*', 'depth'=> new Zend_Db_Expr('COUNT(parent.' . $intPrimary . ') - 1')) )
				->from(array('parent'=> $this->_name ),array($this->_permaUrlColumn => new Zend_Db_Expr('GROUP_CONCAT(parent.' . $this->_permaUrlColumn . ' SEPARATOR "/")')) )
				->where('node.lft BETWEEN parent.lft AND parent.rgt')
				// ->where('sub_tree.url = ?', $argStrUrl )
				->group('node.' . $intPrimary )
				->order('node.lft');
		}
		
		return parent::fetchAll( $objSelect );	
	}
	
	public function fetchWithUrl()
	{
		$intPrimary = current( (array) $this->_primary );

		$objSelect = $this->select()
			->setIntegrityCheck(false)
			->from(array('node'=>$this->_name),array('*', 'depth'=> new Zend_Db_Expr('COUNT(parent.' . $intPrimary . ') - 1')) )
			->from(array('parent'=>$this->_name),array('url' => new Zend_Db_Expr('GROUP_CONCAT(parent.' . $this->_permaUrlColumn . ' SEPARATOR "/")')) )
			->where('node.lft BETWEEN parent.lft AND parent.rgt')
			// ->where('sub_tree.url = ?', $argStrUrl )
			->group('node.' . $intPrimary )
			->order('node.lft');
		
		return $this->fetchAll( $objSelect );	
	}
	
	public function fetchRootNodes( $argStrUrl = false )
	{
		$intPrimary = current( (array) $this->_primary );
		
		$objSubSelect = $this->select();
		$objSubSelect->setIntegrityCheck(false);
		
		$objSubSelect->from(
			array('node'=>'content'),
			array('depth' => new Zend_Db_Expr('COUNT(parent.' . $intPrimary . ') - 1'),'id')
		);
		
		$objSubSelect->from(
			array('parent'=>'content'), 
			array('url' => new Zend_Db_Expr('GROUP_CONCAT( parent.' . $this->_permaUrlColumn . ' SEPARATOR "/")') ) 
		);
		
		$objSubSelect->where('node.lft BETWEEN parent.lft AND parent.rgt');
		$objSubSelect->group('node.id');
		$objSubSelect->order('node.lft');
		
		$objSelect = $this->select()
			->setIntegrityCheck(false)
			->from(
				array('node'=>'content'),
				array(
					'*',
					'active' => new Zend_Db_Expr('IF( LOCATE(node.' . $this->_permaUrlColumn . ',"' . $argStrUrl . '") > 0 ,1,0)')
				)
			)
			->from(array('sub_tree'=> $objSubSelect),array('depth'))
			->where('node.' . $intPrimary . ' = sub_tree.' . $intPrimary )
			->where('sub_tree.depth = 0')
			->order('node.lft');


		return $this->fetchAll($objSelect);
	}

	public function fetchSubHierarch( $argStrUrl = false, Zend_Db_Table_Row_Abstract $argObjRow )
	{
		$intPrimary = current( (array) $this->_primary );
		
		$objSelect = $this->select()
			->setIntegrityCheck(false)
			->from(
				array('node'=> $this->_name), 
				array(
					'*',
					'active' => new Zend_Db_Expr('IF( LOCATE(node.' . $this->_permaUrlColumn . ',"' . $argStrUrl . '") > 0 ,1,0)')
				)
			)
			->from(
				array('parent'=>$this->_name),
				array(
					'depth' => new Zend_Db_Expr('COUNT(parent.id) - (sub_tree.depth + 1)'),
					'url' => new Zend_Db_Expr('GROUP_CONCAT(parent.' . $this->_permaUrlColumn . ' SEPARATOR "/")')
					
				)
			)
			->from(array('sub_parent'=>$this->_name),array())
			->from(array(
				'sub_tree'=> $this->select()
					->setIntegrityCheck(false)
					->from(
						array(
							'node'=>$this->_name
						),
						array('id')
					)
					->from(
						array('parent'=>$this->_name), 
						array('depth' => new Zend_Db_Expr('COUNT(parent.' . $intPrimary . ') - 1'))
					)
					->where('node.lft BETWEEN parent.lft AND parent.rgt')
					->where('node.id = ?', $argObjRow->id )
					->group('node.id')
					->order('node.lft')
			),array())
			->where('node.lft BETWEEN parent.lft AND parent.rgt')
			->where('node.lft BETWEEN sub_parent.lft AND sub_parent.rgt')
			->where('sub_parent.id = sub_tree.id')
			->group('node.id')
			
			->order('node.lft')
			->having('depth > ?', 0);
			
		return parent::fetchAll( $objSelect );

	}
	
	
	public function fetchHierarch( $argStrUrl = false )
	{
		$intPrimary = current( (array) $this->_primary );
		
		$objSelect = $this->select()
			->setIntegrityCheck(false)
			->from(
				array('node'=> $this->_name), 
				array(
					'*',
					'active' => new Zend_Db_Expr('IF( LOCATE(node.' . $this->_permaUrlColumn . ',"' . $argStrUrl . '") > 0 ,1,0)')
				)
			)
			->from(
				array('parent'=>$this->_name),
				array(
					'depth' => new Zend_Db_Expr('COUNT(parent.id) - (sub_tree.depth + 1)'),
					'url' => new Zend_Db_Expr('GROUP_CONCAT(parent.' . $this->_permaUrlColumn . ' SEPARATOR "/")')
					
				)
			)
			->from(array('sub_parent'=>$this->_name),array())
			->from(array(
				'sub_tree'=> $this->select()
					->setIntegrityCheck(false)
					->from(
						array(
							'node'=>$this->_name
						),
						array('id')
					)
					->from(
						array('parent'=>$this->_name), 
						array('depth' => new Zend_Db_Expr('COUNT(parent.' . $intPrimary . ') - 1'))
					)
					->where('node.lft BETWEEN parent.lft AND parent.rgt')
					->group('node.id')
					->order('node.lft')
			),array())
			->where('node.lft BETWEEN parent.lft AND parent.rgt')
			->where('node.lft BETWEEN sub_parent.lft AND sub_parent.rgt')
			->where('sub_parent.id = sub_tree.id')
			->group('node.id')
			
			->order('node.lft');
			
		return parent::fetchAll( $objSelect );

	}

	public function fetchHeritage( $intId )
	{
		$strPrimary = current( (array) $this->_primary );
		
		$objSelect = $this->select()
			->setIntegrityCheck(false)
			->from(array('node' => $this->_name))
			->from(array('parent' => $this->_name),'*')
			->where('node.lft BETWEEN parent.lft AND parent.rgt')
			->where('node.' . $strPrimary . ' = ?', (int) $intId )
			->order('parent.lft');

		return $this->fetchAll($objSelect);
	}
	
	public function findByIdWithUrl( $intId )
	{
		$strPrimary = current( (array) $this->_primary );
		
		$objSelect = $this->select()
			->setIntegrityCheck(false)
			->from(array('node' => $this->_name),'*')
			->from(array('parent' => $this->_name),array('url' => new Zend_Db_Expr('GROUP_CONCAT(parent.' . $this->_permaUrlColumn . ' SEPARATOR "/")')) )
			->where('node.lft BETWEEN parent.lft AND parent.rgt')
			->where('node.' . $strPrimary . ' = ?', (int) $intId )
			->group('node.' . $strPrimary )
			->order('parent.lft');

		return $this->fetchAll($objSelect);
	}
}